package com.demo;

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadTest {
	
	private static Semaphore semaphore = new Semaphore(5);// 设置并发信号量为5
	private static AtomicInteger atomicInteger = new AtomicInteger(0);// 声明原子操作整数，初始化为9
	
	public static void main(String[] args) {
		// 首先介绍一个并发工具包，Semphore（信号量）
		// 这里我们需要用到它的代参构造Semaphore semaphore = new Semaphore(permits);
		// 参数permits的意思是同时可以存在多少个信号，或者说是同时可以并发多少个信号
		// 比如说：我有100个线程，同时并发只并发5个，则设置permits为5
		// 说到这里又涉及到一个问题就是，线程是越多越好么？
		// 答案自然是否定的，这里Google官方给出的最佳并发数是当前服务器内核数+1
		// 也就是说，pertits = cpu(内核数) + 1;假如是4核的则推荐最佳并发数是5
		// 因为我的电脑是4核的，所以这里就举例并发为5，这里不再进行代码的封装，
		// 只是举一个简单的例子

		//Semaphore semaphore = new Semaphore(5);// 设置并发信号量为5

		// 这里我们已经创建好并发数了，那么我们怎么使用呢？
		// 这里介绍两个核心方法，
		// 第一个：semaphore.acquire(); 获取信号或者说获取一把锁
		// 第二个：semaphore.release(); 释放信号或者说释放一把锁

		// 示例代码如下：

		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {

				@Override
				public void run() {
					// 注意：在刚进入方法就需要获得一把锁，再次强调，是刚进入方法就获得一把锁
					
					try {
						semaphore.acquire();// 获取一把锁，因为是在匿名内部类中使用，所以需要将其声明为成员变量

						// 这里我想对线程进行计数，但是是多线程并发，所以不能直接用i++来计数，
						// 因此我们需要进行原子操作，为此，我们再次介绍一个工具包，“原子”，Atomic
						// 这里我们使用整形的AtomicInteger，因为需要在内部类中使用，所以声明为成员变量，设置初始化为0
						
						int current = atomicInteger.getAndIncrement();
						System.out.println("第" + current +"进来了");// 打印日志
						
						Thread.sleep(1000);// 让当前线程睡1秒，模仿耗时操作
						
						System.out.println("第" + current +"出去了");
						
						semaphore.release();// 释放一把锁，必须释放，必须是方法最后一步
						
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}

	}
}